package com.atguigu.daijia.dispatch.xxl.client;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.daijia.common.execption.GuiguException;
import com.atguigu.daijia.common.result.ResultCodeEnum;
import com.atguigu.daijia.dispatch.xxl.config.XxlJobClientConfig;
import com.atguigu.daijia.model.entity.dispatch.XxlJobInfo;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.Objects;

/*
@description:与xxl_job调度中心的交互类
@ClassName XxlJobClient
@author chen
@create 2024-08-25 20:16
@Version 1.0
*/
@SuppressWarnings("WriteOnlyObject")
@Slf4j
@Component
public class XxlJobClient {
    @Resource
    private XxlJobClientConfig xxlJobClientConfig;
    @Resource
    private RestTemplate restTemplate;

    /*
     * @param executorHandler   执行器，任务Handler名称
     * @param param            执行器，任务参数
     * @param corn             调度配置，值含义取决于调度类型
     * @param desc             描述
     * @==============History===============<br/>
     * @Description //   添加任务
     * @Date 2024-8-25 20:24
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return java.lang.Long
     */
    @SneakyThrows
    public Long addJob(String executorHandler,
                       String param,
                       String corn,
                       String desc)
    {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setJobGroup(xxlJobClientConfig.getJobGroupId());
        xxlJobInfo.setJobDesc(desc);
        xxlJobInfo.setAuthor("chen");
        xxlJobInfo.setScheduleType("CRON");
        xxlJobInfo.setScheduleConf(corn);
        xxlJobInfo.setGlueType("BEAN");
        xxlJobInfo.setExecutorHandler(executorHandler);
        xxlJobInfo.setExecutorParam(param);
        xxlJobInfo.setExecutorRouteStrategy("FIRST");
        xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");
        xxlJobInfo.setMisfireStrategy("FIRE_ONCE_NOW");
        xxlJobInfo.setExecutorTimeout(0);
        xxlJobInfo.setExecutorFailRetryCount(0);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);

        String url = xxlJobClientConfig.getAddUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);

        if(response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200)
        {
            log.info("增加xxl执行任务成功,返回信息:{}", response.getBody().toJSONString());
            // 返回任务的id
            return response.getBody().getLong("content");
        }
        log.info("调用xxl增加执行任务失败:{}", Objects.requireNonNull(response.getBody()).toJSONString());
        throw new GuiguException(ResultCodeEnum.DATA_ERROR);
    }


    /*
     * @param jobId      任务id
     * @==============History===============<br/>
     * @Description //   启动任务
     * @Date 2024-8-25 20:26
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return java.lang.Boolean
     */
    public Boolean startJob(Long jobId)
    {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setId(jobId.intValue());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);

        String url = xxlJobClientConfig.getStartJobUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if(response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200)
        {
            log.info("启动xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString());
            return true;
        }
        log.info("启动xxl执行任务失败:{},返回信息:{}", jobId, Objects.requireNonNull(response.getBody()).toJSONString());
        throw new GuiguException(ResultCodeEnum.DATA_ERROR);
    }


    /*
     * @param jobId      任务id
     * @==============History===============<br/>
     * @Description //   停止任务
     * @Date 2024-8-25 20:28
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return java.lang.Boolean
     */
    public Boolean stopJob(Long jobId)
    {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setId(jobId.intValue());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);

        String url = xxlJobClientConfig.getStopJobUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if(response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200)
        {
            log.info("停止xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString());
            return true;
        }
        log.info("停止xxl执行任务失败:{},返回信息:{}", jobId, Objects.requireNonNull(response.getBody()).toJSONString());
        throw new GuiguException(ResultCodeEnum.DATA_ERROR);
    }


    /*
     * @param jobId      任务id
     * @==============History===============<br/>
     * @Description //   删除任务
     * @Date 2024-8-25 20:29
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return java.lang.Boolean
     */
    public Boolean removeJob(Long jobId)
    {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setId(jobId.intValue());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);

        String url = xxlJobClientConfig.getRemoveUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if(response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200)
        {
            log.info("删除xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString());
            return true;
        }
        log.info("删除xxl执行任务失败:{},返回信息:{}", jobId, Objects.requireNonNull(response.getBody()).toJSONString());
        throw new GuiguException(ResultCodeEnum.DATA_ERROR);
    }


    /*
     * @param executorHandler  执行器
     * @param param            执行器参数
     * @param corn             表达式
     * @param desc             描述
     * @==============History===============<br/>
     * @Description //   创建并执行任务
     * @Date 2024-8-25 20:31
     * @Author < a href="15991488967@163.com">chen</ a>
     * @return java.lang.Long
     */
    public Long addAndStart(String executorHandler,
                            String param,
                            String corn,
                            String desc)
    {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setJobGroup(xxlJobClientConfig.getJobGroupId());
        xxlJobInfo.setJobDesc(desc);
        xxlJobInfo.setAuthor("chen");
        xxlJobInfo.setScheduleType("CRON");
        xxlJobInfo.setScheduleConf(corn);
        xxlJobInfo.setGlueType("BEAN");
        xxlJobInfo.setExecutorHandler(executorHandler);
        xxlJobInfo.setExecutorParam(param);
        xxlJobInfo.setExecutorRouteStrategy("FIRST");
        xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");
        xxlJobInfo.setMisfireStrategy("FIRE_ONCE_NOW");
        xxlJobInfo.setExecutorTimeout(0);
        xxlJobInfo.setExecutorFailRetryCount(0);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);

        String url = xxlJobClientConfig.getAddAndStartUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if(response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200)
        {
            log.info("增加并开始执行xxl任务成功,返回信息:{}", response.getBody().toJSONString());
            //content为任务id
            return response.getBody().getLong("content");
        }
        log.info("增加并开始执行xxl任务失败:{}", Objects.requireNonNull(response.getBody()).toJSONString());
        throw new GuiguException(ResultCodeEnum.DATA_ERROR);
    }

}
